package shemes;

import gui.GuiLabel;
import gui.GuiLine;
import gui.GuiScheme;

import java.awt.Point;
import java.util.ArrayList;

import components.*;

public class Counter {

    private static KMOPR KMOPR1;
    private static KMADR KMADR1;
    private static MP MP1;
    private static REG mPC;
    private static OR ORmPC;
    private static NOT NOTmPC;
    private static MicroMEM mMEM;
    private static IntToBools mCWbits8, mCWbits23, mCWbits5;
    private static BoolsToInt zeroes;
    private static GuiScheme gui;

    public static GuiScheme getGui() {
        return gui;
    }

    public static void init() {
        KMOPR1 = new KMOPR();
        KMOPR1.getOut(0).setNumOfLines(8);

        KMADR1 = new KMADR();
        KMADR1.getOut(0).setNumOfLines(8);

        MP1 = new MP(4);
        MP1.getOut(0).setNumOfLines(8);
        MP1.getOut(0).setIsInt();

        mPC = new REG(1, "mPC");
        mPC.getOut(0).setNumOfLines(8);
        mPC.getOut(0).setIsInt();

        ORmPC = new OR(3);
        NOTmPC = new NOT();

        mMEM = new MicroMEM(230);

        mCWbits8 = new IntToBools(1, 8);
        mCWbits23 = new IntToBools(1, 23);
        mCWbits5 = new IntToBools(1, 5);

        zeroes = new BoolsToInt(8, 8);
    }

    public static void connect() {
        KMOPR1.setInputPin(0, Fetch2.NOP());
        KMOPR1.setInputPin(1, Fetch2.HALT());
        KMOPR1.setInputPin(2, Fetch2.INTD());
        KMOPR1.setInputPin(3, Fetch2.INTE());
        KMOPR1.setInputPin(4, Fetch2.TRPD());
        KMOPR1.setInputPin(5, Fetch2.TRPE());
        KMOPR1.setInputPin(6, Fetch2.LDB());
        KMOPR1.setInputPin(7, Fetch2.LDW());
        KMOPR1.setInputPin(8, Fetch2.STB());
        KMOPR1.setInputPin(9, Fetch2.STW());

        KMOPR1.setInputPin(10, Fetch2.POPB());
        KMOPR1.setInputPin(11, Fetch2.POPW());
        KMOPR1.setInputPin(12, Fetch2.PUSHB());
        KMOPR1.setInputPin(13, Fetch2.PUSHW());
        KMOPR1.setInputPin(14, Fetch2.LDIVTP());
        KMOPR1.setInputPin(15, Fetch2.STIVTP());
        KMOPR1.setInputPin(16, Fetch2.LDIMR());
        KMOPR1.setInputPin(17, Fetch2.STIMR());
        KMOPR1.setInputPin(18, Fetch2.LDSP());
        KMOPR1.setInputPin(19, Fetch2.STSP());
        KMOPR1.setInputPin(20, Fetch2.ADD());
        KMOPR1.setInputPin(21, Fetch2.SUB());
        KMOPR1.setInputPin(22, Fetch2.INC());
        KMOPR1.setInputPin(23, Fetch2.DEC());
        KMOPR1.setInputPin(24, Fetch2.AND());
        KMOPR1.setInputPin(25, Fetch2.OR());
        KMOPR1.setInputPin(26, Fetch2.XOR());
        KMOPR1.setInputPin(27, Fetch2.NOT());
        KMOPR1.setInputPin(28, Fetch2.ASR());
        KMOPR1.setInputPin(29, Fetch2.LSR());
        KMOPR1.setInputPin(30, Fetch2.ROR());
        KMOPR1.setInputPin(31, Fetch2.RORC());
        KMOPR1.setInputPin(32, Fetch2.ASL());
        KMOPR1.setInputPin(33, Fetch2.LSL());
        KMOPR1.setInputPin(34, Fetch2.ROL());
        KMOPR1.setInputPin(35, Fetch2.ROLC());
        KMOPR1.setInputPin(36, Fetch2.BEQL());
        KMOPR1.setInputPin(37, Fetch2.BNEQL());
        KMOPR1.setInputPin(38, Fetch2.BNEG());
        KMOPR1.setInputPin(39, Fetch2.BNNEG());
        KMOPR1.setInputPin(40, Fetch2.BOVF());
        KMOPR1.setInputPin(41, Fetch2.BNOVF());
        KMOPR1.setInputPin(42, Fetch2.BCAR());
        KMOPR1.setInputPin(43, Fetch2.BNCAR());
        KMOPR1.setInputPin(44, Fetch2.BGRT());
        KMOPR1.setInputPin(45, Fetch2.BGRTE());
        KMOPR1.setInputPin(46, Fetch2.BLSS());
        KMOPR1.setInputPin(47, Fetch2.BLSSE());
        KMOPR1.setInputPin(48, Fetch2.BGRTU());
        KMOPR1.setInputPin(49, Fetch2.BGRTEU());
        KMOPR1.setInputPin(50, Fetch2.BLSSU());
        KMOPR1.setInputPin(51, Fetch2.BLSSEU());
        KMOPR1.setInputPin(52, Fetch2.JMP());
        KMOPR1.setInputPin(53, Fetch2.INT());
        KMOPR1.setInputPin(54, Fetch2.JSR());
        KMOPR1.setInputPin(55, Fetch2.RTI());
        KMOPR1.setInputPin(56, Fetch2.RTS());

        KMADR1.setInputPin(0, Fetch2.regdir());
        KMADR1.setInputPin(1, Fetch2.regind());
        KMADR1.setInputPin(2, Fetch2.memdir());
        KMADR1.setInputPin(3, Fetch2.memind());
        KMADR1.setInputPin(4, Fetch2.regindpom());
        KMADR1.setInputPin(5, Fetch2.bxpom());
        KMADR1.setInputPin(6, Fetch2.pcpom());
        KMADR1.setInputPin(7, Fetch2.imm());

        MP1.setInputPin(0, mMEM.getOut(0));
        MP1.setInputPin(1, KMADR1.getOut(0));
        MP1.setInputPin(2, KMOPR1.getOut(0));
        Pin p = new Pin(0, 1);
        p.setIsInt();
        MP1.setInputPin(3, p);
        MP1.setCtrl(0, Uprav1.bradr());
        MP1.setCtrl(1, Uprav1.bropr());

        ORmPC.setInputPin(0, Uprav1.bradr());
        ORmPC.setInputPin(1, Uprav1.bropr());
        ORmPC.setInputPin(2, Uprav1.branch());
        NOTmPC.setInputPin(0, ORmPC.getOut(0));

        mPC.setInputPin(0, MP1.getOut(0));
        mPC.setPinLd(ORmPC.getOut(0));
        mPC.setPinInc(NOTmPC.getOut(0));

        mMEM.setInputPin(0, mPC.getOut(0));

        mCWbits8.setInputPin(0, mMEM.getOut(0));
        mCWbits5.setInputPin(0, mMEM.getOut(1));
        mCWbits23.setInputPin(0, mMEM.getOut(2));

        for (int i = 0; i < 8; i++) {
            zeroes.setInputPin(i, new Pin(false));
        }

    }

    public static void gui() {
        GuiLine line; // Pomocna promenljiva
        gui = new GuiScheme("src/images/Counter.png");

        ArrayList<ArrayList<Point>> sections;
        ArrayList<Point> points;


        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(120, 96));
        points.add(new Point(120, 105));
        sections.add(points);
        line = new GuiLine(sections, Fetch2.NOP());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(135, 96));
        points.add(new Point(135, 105));
        sections.add(points);
        line = new GuiLine(sections, Fetch2.HALT());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(214, 96));
        points.add(new Point(214, 105));
        sections.add(points);
        line = new GuiLine(sections, Fetch2.RTS());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(271, 96));
        points.add(new Point(271, 105));
        sections.add(points);
        line = new GuiLine(sections, Fetch2.regdir());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(286, 96));
        points.add(new Point(286, 105));
        sections.add(points);
        line = new GuiLine(sections, Fetch2.regind());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(365, 96));
        points.add(new Point(365, 105));
        sections.add(points);
        line = new GuiLine(sections, Fetch2.imm());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(167, 154));
        points.add(new Point(167, 209));
        sections.add(points);
        line = new GuiLine(sections, KMOPR1.getOut(0));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(318, 154));
        points.add(new Point(318, 181));
        points.add(new Point(197, 181));
        points.add(new Point(197, 209));
        sections.add(points);
        line = new GuiLine(sections, KMADR1.getOut(0));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(137, 190));
        points.add(new Point(137, 209));
        sections.add(points);
        line = new GuiLine(sections, zeroes.getOut(0));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(320, 504));
        points.add(new Point(320, 521));
        points.add(new Point(427, 521));
        points.add(new Point(427, 190));
        points.add(new Point(227, 190));
        points.add(new Point(227, 209));
        sections.add(points);
        line = new GuiLine(sections, mMEM.getOut(0));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(257, 218));
        points.add(new Point(250, 218));
        sections.add(points);
        line = new GuiLine(sections, Uprav1.bradr());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(257, 237));
        points.add(new Point(250, 237));
        sections.add(points);
        line = new GuiLine(sections, Uprav1.bropr());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(182, 247));
        points.add(new Point(182, 284));
        sections.add(points);
        line = new GuiLine(sections, MP1.getOut(0));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(106, 303));
        points.add(new Point(114, 303));
        sections.add(points);
        line = new GuiLine(sections, LogicalComponent.getCPUCLK());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(322, 292));
        points.add(new Point(314, 292));
        sections.add(points);
        line = new GuiLine(sections, Uprav1.bradr());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(322, 303));
        points.add(new Point(312, 303));
        sections.add(points);
        line = new GuiLine(sections, Uprav1.bropr());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(322, 315));
        points.add(new Point(314, 315));
        sections.add(points);
        line = new GuiLine(sections, Uprav1.branch());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(292, 303));
        points.add(new Point(284, 303));
        points.add(new Point(284, 294));
        points.add(new Point(250, 294));
        sections.add(points);
        points = new ArrayList<Point>();
        points.add(new Point(284, 303));
        points.add(new Point(284, 313));
        points.add(new Point(255, 313));
        sections.add(points);
        line = new GuiLine(sections, ORmPC.getOut(0));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(182, 322));
        points.add(new Point(182, 360));
        sections.add(points);
        line = new GuiLine(sections, mPC.getOut(0));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(106, 371));
        points.add(new Point(114, 371));
        sections.add(points);
        line = new GuiLine(sections, new Pin(true));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(106, 390));
        points.add(new Point(114, 390));
        sections.add(points);
        line = new GuiLine(sections, new Pin(false));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(378, 444));
        points.add(new Point(386, 444));
        sections.add(points);
        line = new GuiLine(sections, LogicalComponent.getCPUCLK());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(386, 467));
        points.add(new Point(378, 467));
        sections.add(points);
        line = new GuiLine(sections, new Pin(true));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(78, 473));
        points.add(new Point(78, 481));
        sections.add(points);
        line = new GuiLine(sections, Counter.mCW35());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(155, 473));
        points.add(new Point(155, 481));
        sections.add(points);
        line = new GuiLine(sections, Counter.mCW13());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(191, 473));
        points.add(new Point(191, 481));
        sections.add(points);
        line = new GuiLine(sections, Counter.mCW12());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(235, 473));
        points.add(new Point(235, 481));
        sections.add(points);
        line = new GuiLine(sections, Counter.mCW8());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(291, 474));
        points.add(new Point(291, 481));
        sections.add(points);
        line = new GuiLine(sections, mCWbits8.getOut(7));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(352, 473));
        points.add(new Point(352, 481));
        sections.add(points);
        line = new GuiLine(sections, mCWbits8.getOut(0));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(123, 503));
        points.add(new Point(123, 549));
        points.add(new Point(152, 549));
        points.add(new Point(152, 558));
        sections.add(points);
        line = new GuiLine(sections, mMEM.getOut(2));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(212, 502));
        points.add(new Point(212, 549));
        points.add(new Point(427, 549));
        points.add(new Point(427, 558));
        sections.add(points);
        line = new GuiLine(sections, mMEM.getOut(1));
        gui.addLine(line);


        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(340, 566));
        points.add(new Point(350, 566));
        sections.add(points);
        line = new GuiLine(sections, Exec2.START());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(340, 581));
        points.add(new Point(350, 581));
        sections.add(points);
        line = new GuiLine(sections, Bus1.hack());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(340, 596));
        points.add(new Point(350, 596));
        sections.add(points);
        line = new GuiLine(sections, Bus1.fcCPU());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(340, 626));
        points.add(new Point(350, 626));
        sections.add(points);
        line = new GuiLine(sections, Fetch3.gropr());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(340, 657));
        points.add(new Point(350, 657));
        sections.add(points);
        line = new GuiLine(sections, Fetch3.I1());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(340, 687));
        points.add(new Point(350, 687));
        sections.add(points);
        line = new GuiLine(sections, new Pin(false));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(505, 566));
        points.add(new Point(514, 566));
        sections.add(points);
        line = new GuiLine(sections, Fetch2.regdir());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(506, 596));
        points.add(new Point(514, 596));
        sections.add(points);
        line = new GuiLine(sections, Fetch2.NOP());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(505, 626));
        points.add(new Point(514, 626));
        sections.add(points);
        line = new GuiLine(sections, Exec4.brpom());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(505, 657));
        points.add(new Point(514, 657));
        sections.add(points);
        line = new GuiLine(sections, Intr1.prekid());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(514, 687));
        points.add(new Point(505, 687));
        sections.add(points);
        line = new GuiLine(sections, new Pin(false));
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(395, 694));
        points.add(new Point(395, 713));
        sections.add(points);
        line = new GuiLine(sections, Uprav1.bradr());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(433, 694));
        points.add(new Point(433, 711));
        sections.add(points);
        line = new GuiLine(sections, Uprav1.bropr());
        gui.addLine(line);

        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(471, 694));
        points.add(new Point(471, 711));
        sections.add(points);
        line = new GuiLine(sections, Uprav1.branch());
        gui.addLine(line);


        sections = new ArrayList<ArrayList<Point>>();
        points = new ArrayList<Point>();
        points.add(new Point(182, 398));
        points.add(new Point(182, 436));
        sections.add(points);
        line = new GuiLine(sections, zeroes.getOut(0));
        gui.addLine(line);

        //LABELE:
        gui.addLabel(new GuiLabel(150, 167, KMOPR1.getOut(0)));
        gui.addLabel(new GuiLabel(301, 167, KMADR1.getOut(0)));
        gui.addLabel(new GuiLabel(372, 203, mMEM.getOut(0)));
        gui.addLabel(new GuiLabel(189, 262, MP1.getOut(0)));
        gui.addLabel(new GuiLabel(189, 358, mPC.getOut(0)));
        gui.addLabel(new GuiLabel(130, 520, mMEM.getOut(2)));
        gui.addLabel(new GuiLabel(219, 520, mMEM.getOut(1)));
        gui.addLabel(new GuiLabel(327, 520, mMEM.getOut(0)));
        
            
    }

    public static Pin KMADR() {
        return KMADR1.getOut(0);
    }

    public static Pin KMOPR() {
        return KMOPR1.getOut(0);
    }

    public static Pin mPC() {
        return mPC.getOut(0);
    }

    public static Pin mCW8() {
        return mCWbits5.getOut(0);
    }

    public static Pin mCW9() {
        return mCWbits5.getOut(1);
    }

    public static Pin mCW10() {
        return mCWbits5.getOut(2);
    }

    public static Pin mCW11() {
        return mCWbits5.getOut(3);
    }

    public static Pin mCW12() {
        return mCWbits5.getOut(4);
    }

    public static Pin mCW13() {
        return mCWbits23.getOut(0);
    }

    public static Pin mCW14() {
        return mCWbits23.getOut(1);
    }

    public static Pin mCW15() {
        return mCWbits23.getOut(2);
    }

    public static Pin mCW16() {
        return mCWbits23.getOut(3);
    }

    public static Pin mCW17() {
        return mCWbits23.getOut(4);
    }

    public static Pin mCW18() {
        return mCWbits23.getOut(5);
    }

    public static Pin mCW19() {
        return mCWbits23.getOut(6);
    }

    public static Pin mCW20() {
        return mCWbits23.getOut(7);
    }

    public static Pin mCW21() {
        return mCWbits23.getOut(8);
    }

    public static Pin mCW22() {
        return mCWbits23.getOut(9);
    }

    public static Pin mCW23() {
        return mCWbits23.getOut(10);
    }

    public static Pin mCW24() {
        return mCWbits23.getOut(11);
    }

    public static Pin mCW25() {
        return mCWbits23.getOut(12);
    }

    public static Pin mCW26() {
        return mCWbits23.getOut(13);
    }

    public static Pin mCW27() {
        return mCWbits23.getOut(14);
    }

    public static Pin mCW28() {
        return mCWbits23.getOut(15);
    }

    public static Pin mCW29() {
        return mCWbits23.getOut(16);
    }

    public static Pin mCW30() {
        return mCWbits23.getOut(17);
    }

    public static Pin mCW31() {
        return mCWbits23.getOut(18);
    }

    public static Pin mCW32() {
        return mCWbits23.getOut(19);
    }

    public static Pin mCW33() {
        return mCWbits23.getOut(20);
    }

    public static Pin mCW34() {
        return mCWbits23.getOut(21);
    }

    public static Pin mCW35() {
        return mCWbits23.getOut(22);
    }

    public static REG mPCREG() {
        return mPC;
    }
}
